package com.valenx.distributedmulticamerasystem.camera.codec;



import com.valenx.distributedmulticamerasystem.camera.api.CodecListener;
import com.valenx.distributedmulticamerasystem.camera.utils.LogUtil;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.media.codec.Codec;
import ohos.media.common.BufferInfo;
import ohos.media.common.Format;

import java.nio.ByteBuffer;

//编码器封装类
public class CodecEncoder {
    private static final int WRITE_BUFFER = 1;
    private static final int STOP_CODEC = 2;
    private final MyEventHandler encoderHandler;
    private Codec encoder;//编码器实例
    private CodecListener codecListener;//传出编码完成数据的监听器
    private boolean isOpen = false;
//=============================================================================================================

    //构造器
    private CodecEncoder(Builder builder) {
        initEncoder(builder.format);
        encoderHandler = new MyEventHandler(EventRunner.create(CodecEncoder.class.getSimpleName()));
    }
//=============================================================================================================

    //Builder内部类
    public static class Builder {
        private Format format;

        public Builder() {
        }

        //设置格式
        public Builder setFormat(Format format) {
            this.format = format;
            return this;
        }

        //创建编码器
        public CodecEncoder create() {
            return new CodecEncoder(this);
        }
    }
//=============================================================================================================

    //事件处理器子类
    private class MyEventHandler extends EventHandler {
        MyEventHandler(EventRunner eventRunner) {
            super(eventRunner);
        }
        @Override
        protected void processEvent(InnerEvent event) {
            switch (event.eventId) {
                //将数据传入编码器
                case WRITE_BUFFER:
                    byte[] bytes = (byte[]) (event.object);
                    LogUtil.info("CodecEncoder:", "开始编码");
                    if (isOpen) {
                        ByteBuffer byteBuffer = encoder.getAvailableBuffer(100);
                        if (byteBuffer != null) {
                            byteBuffer.clear();
                            byteBuffer.put(bytes);
                            BufferInfo info = new BufferInfo();
                            info.size = bytes.length;
                            info.offset = 0;
                            info.timeStamp = System.currentTimeMillis() * 1000;
                            boolean isSuccess = encoder.writeBuffer(byteBuffer, info);
                            LogUtil.info("CodecEncoder:", "编码器编码完成，结果:" + isSuccess);
                        }
                    }
                    break;
                //停止编码
                case STOP_CODEC:
                    LogUtil.info("CodecEncoder:", "停止编码");
                    if (encoder.stop() && encoder.release()) {
                        encoder = null;
                        isOpen = false;
                    }
                    break;
                default:
                    break;
            }
        }
    }
//************************************************************************************************************

    //初始化编码器
    private void initEncoder(Format fmt) {
        LogUtil.info("CodecEncoder:", "初始化编码器");
        encoder = Codec.createEncoder();
        encoder.setCodecFormat(fmt);

        //注册监听器用来异步接收编码或解码后的数据。
        encoder.registerCodecListener(
                new Codec.ICodecListener() {
                    @Override
                    public void onReadBuffer(ByteBuffer byteBuffer, BufferInfo bufferInfo, int tag) {
                        LogUtil.info("CodecEncoder:", "onReadBuffer返回编码后数据");
                        if (codecListener != null) {
                            //收到编码后的数据，通过外部监听器传出数据
                            codecListener.onGetEncodedBuffer(byteBuffer, bufferInfo);
                        }
                    }

                    @Override
                    public void onError(int tag, int tag1, int tag2) {
                        LogUtil.info("CodecEncoder:", "编码错误");
                    }
                });
    }
//************************************************************************************************************

    //打开编码器
    public void openEncoder() {
        if (!isOpen) {
            if (encoder.start()) {
                isOpen = true;
            }
        }
    }
//************************************************************************************************************


    //开始编码（开始传入数据）
    public void startEncode(byte[] bytes) {
        if (isOpen) {
            InnerEvent innerEvent = InnerEvent.get(WRITE_BUFFER, 0, bytes);
            encoderHandler.sendEvent(innerEvent, 0, EventHandler.Priority.IMMEDIATE);
        }
    }
//************************************************************************************************************

    //停止编码
    public void stopEncode() {
        if (isOpen) {
            encoderHandler.sendEvent(STOP_CODEC);
        }
    }
//************************************************************************************************************

    //设置接收数据的外部监听器
    public void setEncodeListener(CodecListener listener) {
        codecListener = listener;
    }
//-------------------------------------------------------------------------------------------------------------

    //编码器是否开启
    public boolean isOpen() {
        return isOpen;
    }
}
